package sueca2011;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Renzo
 */
public abstract class IA extends Jogador implements Observer{

    protected Jogador[] ordem;
    protected Carta trunfo;
    protected Jogador parceiro;

    private ArrayList<Jogada> jogadas;

    private HashMap<Carta,Float> probs = new HashMap<Carta, Float>();

    private int tamMemoria;
    public IA(String nome, int tamMemoria) throws RemoteException{
        super(nome);
        this.tamMemoria = tamMemoria;
        jogadas = new ArrayList<Jogada>(tamMemoria);
        for(int i=0;i<this.cartasIniciais.size();i++){
            probs.put(this.cartasIniciais.get(i), Float.valueOf(0));
        }
    }
    
    public void escolheJogada(Carta carta) throws RemoteException {
        escolheJogada();
    }

    public abstract void escolheJogada() throws RemoteException;

    private void atualizaProbabilidades(){
        normalizar();
    }

    private void normalizar(){
        Iterator<Float> it = this.probs.values().iterator();
        float soma=0;
        while(it.hasNext())
            soma+=it.next().floatValue();

        Iterator<Entry<Carta, Float>> itC = probs.entrySet().iterator();

        Entry<Carta,Float> n;
        while(itC.hasNext()){
            n=itC.next();
            n.setValue(n.getValue()/soma);
        }
    }

    protected void reportarJogada(Jogada jogada){
        if(tamMemoria>0){
            if(this.jogadas.size()==tamMemoria)
                this.jogadas.remove(0);
            this.jogadas.add(jogada);
            this.probs.put(jogada.getCartaJogada(), 0.0f);
            this.atualizaProbabilidades();
        }
        this.novaJogada(jogada);
    }

    protected abstract boolean validaCarta(Carta carta) throws RemoteException;

    protected ArrayList<Carta> getCartasValidas() throws RemoteException{
        ArrayList<Carta> validas = new ArrayList<Carta>();
        Iterator<Carta> it = cartasNaMao.iterator();
        Carta c;
        while(it.hasNext()){
            c = it.next();
            if(this.validaCarta(c)){
                validas.add(c);
            }
        }
        return validas;
    }

    protected abstract void novaJogada(Jogada jogada);
    protected abstract void novaRodada();
    protected abstract void novoJogo();

    public void update(Observable o, Object o1) {
        Jogador jogador;
        if(o instanceof Rodada && o1 instanceof AlertaVez){
            jogador = ((AlertaVez)o1).getJogador();
            if(jogador==this){
                try {
                    this.escolheJogada();
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        }else if(o1 instanceof AlertaJogada){
            Jogada jogada = ((AlertaJogada)o1).getJogada();
            this.reportarJogada(jogada);
        } else if(o1 instanceof InicioRodada) {
            this.ordem = ((InicioRodada)o1).getOrdem();
            this.novaRodada();
        } else if(o1 instanceof AlertaInicioJogo) {
            try {
                trunfo = ((AlertaInicioJogo)o1).getTrunfo();
                if(this.getTime().getJogador1()==this)
                    parceiro = this.getTime().getJogador2();
                else
                    parceiro = this.getTime().getJogador1();
                Carta[] cartas = ((AlertaInicioJogo)o1).getCartas();
                
                int count=cartas.length-probs.size();
                
                float p = 1.0f/(float)count;

                for(int i=0;i<cartas.length;i++)
                    if(!probs.containsKey(cartas[i]))
                        probs.put(cartas[i], p);
                    
                this.novoJogo();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}
